using System;
using Pine.Lexer;
using SP=Pine.SourceParser.pinedl;

namespace Pine.SourceParser
{
	public static class CommonTokenExtensions {
		public static AdaptedToken ToAdapted(this Antlr.Runtime.IToken self) {
			return self as AdaptedToken;
		}
		
		public static Token ToSource(this Antlr.Runtime.IToken self) {
			AdaptedToken token = self.ToAdapted();
			if (token == null)
				return null;
			return token.SourceToken;
		}
	}
	
	public class AdaptedToken : Antlr.Runtime.CommonToken
	{
		public Token SourceToken { get; private set; }
		
		public static int AntlrType(Token t) {			
			switch (t.Type) {
			case TokenType.Word: return SP.WORD;
			case TokenType.Number: return SP.NUMBER;
			case TokenType.CharConstant: return SP.CHARCONST;
			case TokenType.StringConstant: return SP.STRINGCONST;
			case TokenType.End: return SP.EOF;
			}
			if (t.Type == TokenType.Symbol) {
				switch ((Symbol) t.Content) {
				case Symbol.LeftParenthesis: return SP.LPAREN;
				case Symbol.RightParenthesis: return SP.RPAREN;
				case Symbol.Colon: return SP.COLON;
				case Symbol.Semicolon: return SP.SEMICOLON;
				case Symbol.Comma: return SP.COMMA;
				case Symbol.Dot: return SP.DOT;
				case Symbol.Ellipsis: return SP.ELLIPSIS;
				case Symbol.LeftBlock: return SP.LBLOCK;
				case Symbol.RightBlock: return SP.RBLOCK;
				case Symbol.Equal: return SP.EQUAL;
				case Symbol.Plus: return SP.PLUS;
				case Symbol.Minus: return SP.MINUS;
				case Symbol.Times: return SP.MULT;
				case Symbol.LessThan: return SP.LESS;
				case Symbol.LessOrEqual: return SP.LESSOREQUAL;
				case Symbol.GreaterThan: return SP.GREATER;
				case Symbol.GreaterOrEqual: return SP.GREATEROREQUAL;
				case Symbol.Equals: return SP.EQUALS;
				case Symbol.NotEqual: return SP.NOTEQUAL;
				case Symbol.Increment: return SP.INCREMENT;
				case Symbol.Decrement: return SP.DECREMENT;
				case Symbol.LeftArray: return SP.LARRAY;
				case Symbol.RightArray: return SP.RARRAY;
				case Symbol.ArrayKeyValue: return SP.ARRAYKEYVALUE;
				case Symbol.BitwiseNot: return SP.BITNOT;
				case Symbol.LogicalNot: return SP.LOGNOT;
				case Symbol.LogicalAnd: return SP.LOGICALAND;
				case Symbol.LogicalOr: return SP.LOGICALOR;
				}
			}
			if (t.Type == TokenType.Keyword) {
				switch ((string) t.Content) {
				case "break": return SP.BREAK;
				case "callee": return SP.CALLEE;
				case "const": return SP.CONST;
				case "continue": return SP.CONTINUE;
				case "do": return SP.DO;
				case "else": return SP.ELSE;
				case "false": return SP.FALSE;
				case "for": return SP.FOR;
				case "function": return SP.FUNCTION;
				case "if": return SP.IF;
				case "null": return SP.NULL;
				case "number": return SP.NUMBERKEYWORD;
				case "return": return SP.RETURN;
				case "this": return SP.THIS;
				case "true": return SP.TRUE;
				case "var": return SP.VAR;
				case "while": return SP.WHILE;
				}
			}
			return -1234;
		}
		
		public AdaptedToken (Token token) : base(AntlrType(token), token.ToString())
		{
			SourceToken = token;
			Channel = 0;
			Line = token.Line;
			CharPositionInLine = token.Col;
		}
	}
}

